package org.xteam.pascal.parser;

import java_cup.runtime.*;
import org.xteam.pascal.parser.IPascalTokens;

import org.xteam.parser.runtime.IErrorReporter;

%%

%class PascalLexer
%implements IPascalTokens
%cupsym IPascalTokens
%cup
%public
%char

DIGIT		= [0-9]
LETTER		= [a-zA-Z_]
IDENT		= {LETTER}({LETTER}|{DIGIT})*
FLOAT1		= {DIGIT}+"." {DIGIT}+ ("e" ("-")? {DIGIT}+)?
FLOAT2		= {DIGIT}+ "e" ("-")? {DIGIT}+
FLOAT		= {FLOAT1} | {FLOAT2}

%{

	private StringBuffer buffer = new StringBuffer();
	private IErrorReporter reporter;
	private int start;
	
	public PascalLexer(java.io.Reader reader, IErrorReporter reporter) {
		this(reader);
		this.reporter = reporter;
	}

	public Symbol symbol(int kind) {
		return new Symbol(kind, yychar, yychar+yylength(), null);
	}
	
	public Symbol symbol(int kind, Object value) {
		return new Symbol(kind, yychar, yychar+yylength(), value);
	}
	
	public Symbol symbol(int kind, int start, int end, Object value) {
		return new Symbol(kind, start, end, value);
	}
	
	public int initialState() {
		return YYINITIAL;
	}
	
	public int getState() {
		return yystate();
	}
	
	public void setState(int s) {
		yybegin(s);
	}
	
%}

%state STR

%%

<YYINITIAL> {

"{"[^}]*"}" 			{ /* ignore comments */ }
[ \t\f\r\b\n]+		{ /* ignore white spaces */ }

"and"		{ return symbol(IPascalTokens.AND); }
"array"		{ return symbol(IPascalTokens.ARRAY); }
"begin"		{ return symbol(IPascalTokens.BEGIN); }
"case"	{ return symbol(IPascalTokens.CASE); }
"const"	{ return symbol(IPascalTokens.CONST); }
"div"			{ return symbol(IPascalTokens.DIV); }
"downto"			{ return symbol(IPascalTokens.DOWNTO); }
"do"			{ return symbol(IPascalTokens.DO); }
"else"		{ return symbol(IPascalTokens.ELSE); }
"end"		{ return symbol(IPascalTokens.END); }
"file"		{ return symbol(IPascalTokens.FILE); }
"for"		{ return symbol(IPascalTokens.FOR); }
"forward"		{ return symbol(IPascalTokens.FORWARD); }
"goto"		{ return symbol(IPascalTokens.GOTO); }
"function"		{ return symbol(IPascalTokens.FUNCTION); }
"if"		{ return symbol(IPascalTokens.IF); }
"label"		{ return symbol(IPascalTokens.LABEL); }
"mod"			{ return symbol(IPascalTokens.MOD); }
"not"			{ return symbol(IPascalTokens.NOT); }
"of"		{ return symbol(IPascalTokens.OF); }
"or"		{ return symbol(IPascalTokens.OR); }
"packed"		{ return symbol(IPascalTokens.PACKED); }
"procedure"	{ return symbol(IPascalTokens.PROCEDURE); }
"program"		{ return symbol(IPascalTokens.PROGRAM); }
"record"		{ return symbol(IPascalTokens.RECORD); }
"repeat"		{ return symbol(IPascalTokens.REPEAT); }
"then"		{ return symbol(IPascalTokens.THEN); }
"to"			{ return symbol(IPascalTokens.TO); }
"type"		{ return symbol(IPascalTokens.TYPE); }
"until"		{ return symbol(IPascalTokens.UNTIL); }
"var"		{ return symbol(IPascalTokens.VAR); }
"while"		{ return symbol(IPascalTokens.WHILE); }
"with"		{ return symbol(IPascalTokens.WITH); }

":="			{ return symbol(IPascalTokens.ASSIGN); }
".."		{ return symbol(IPascalTokens.RANGE); }
"("			{ return symbol(IPascalTokens.LPAR); }
")"			{ return symbol(IPascalTokens.RPAR); }
"["			{ return symbol(IPascalTokens.LBRT); }
"]"			{ return symbol(IPascalTokens.RBRT); }
"<"			{ return symbol(IPascalTokens.LT); }
">"			{ return symbol(IPascalTokens.GT); }
">="			{ return symbol(IPascalTokens.GE); }
"<="			{ return symbol(IPascalTokens.LE); }
"<>"			{ return symbol(IPascalTokens.NE); }
";"			{ return symbol(IPascalTokens.SEMI); }
":"			{ return symbol(IPascalTokens.COLO); }
","			{ return symbol(IPascalTokens.COMA); }
"-"			{ return symbol(IPascalTokens.MINUS); }
"*"			{ return symbol(IPascalTokens.STAR); }
"/"			{ return symbol(IPascalTokens.SLASH); }
"="			{ return symbol(IPascalTokens.EQUALS); }
"^"			{ return symbol(IPascalTokens.HAT); }
"|"			{ return symbol(IPascalTokens.OR); }
"+"			{ return symbol(IPascalTokens.PLUS); }

"\."			{ return symbol(IPascalTokens.DOT); }
"\'"		{ start = yychar; buffer.setLength(0); yybegin(STR); }

{IDENT}		{ return symbol(IPascalTokens.IDENT, yytext()); }
{FLOAT}		{ return symbol(IPascalTokens.NUMBER, yytext()); }
{DIGIT}+		{ return symbol(IPascalTokens.INTEGER, yytext()); }
.			{ reporter.reportError(yychar, 1, "bad character \'"+yycharat(0)+"\'");
				throw new java.io.IOException("bad character \'"+yycharat(0)+"\'"); }
<<EOF>>		{ return symbol(IPascalTokens.EOF); }
}

<STR> {
"\'"				{ yybegin(YYINITIAL); return symbol(IPascalTokens.STRING, start, yychar + yylength(), buffer.toString()); }
[^\'\n]+			{ buffer.append(yytext()); }
"\'\'"				{ buffer.append('\''); }
[\n]				{ reporter.reportError(start, yychar-start, "unterminated string");
						yybegin(YYINITIAL); return symbol(IPascalTokens.STRING, buffer.toString()); }
}
